-include("rumCom.hrl").
%% 应用名字
-define(RumAppName, eRum).

%% 三元表达式
-define(IIF(Cond, Ret1, Ret2), (case Cond of true -> Ret1; _ -> Ret2 end)).

%% 错误日志宏定义
-define(ERR(Format), error_logger:error_msg(Format)).
-define(ERR(Format, Args), error_logger:error_msg(Format, Args)).

-define(Print(Args), io:format("IMY************~p~n", [Args])).

%% 额外进程字典key
-define(PdMdKey, pdRumMd).
-define(RumTrackSink, '__trace_sink').

%% 旋转日志超时时间
-define(RumRotateTimeout, 100000).

%% 部分默认配置值
-define(RumDefTracer, rumDefTracer).
-define(RumErrLogSink, errLoggerEvent).

%% rumBkdConsole的选项
-type rumConsoleOpt() ::
   {id, atom() | {atom(), atom()}} |
   {use_stderr, boolean()} |
   {group_leader, false | pid() | atom()} |
   {formatTer, atom()} |
   {formatCfg, list()}.

%% rumBkdFile的选项
-type rumFileOpt() ::
   {id, atom()} |
   {file, binary()} |
   {level, rumAtomLevel() | atom()} |
   {size, non_neg_integer()} |
   {date, string()} |
   {count, non_neg_integer()} |
   {rotator, atom()} |
   {hWM, non_neg_integer()} |
   %% 对于特定的接收器事件队列刷新，请使用改选项
   {flushQueue, boolean()} |
   %% 对于接收器 如果flush_queue为true，则可以设置消息队列长度阈值，在该阈值处将开始丢弃消息。默认阈值为0，
   %% 这意味着如果flush_queue为true，则超过高水位标记时将丢弃消息，而不管消息队列的长度如何。：
   {flushThr, non_neg_integer()} |
   {syncInt, non_neg_integer()} |
   {syncSize, non_neg_integer()} |
   {syncOn, rumAtomLevel()} |
   {checkInt, non_neg_integer()} |
   {formatTer, atom()} |
   {formatCfg, term()}.

%% BkdFile选项默认值
-define(RumDefLogLevel, info).
-define(RumDefRotateSize, 10485760).      %% 10mb
-define(RumDefRotateDate, "$D0").         %% midnight
-define(RumDefRotateCnt, 5).
-define(RumDefRotateMod, rumRotatorIns).
-define(RumDefSyncLevel, error).
-define(RumDefSyncInt, 1000).             %% 单位毫秒
-define(RumDefSyncSize, 1024 * 64).       %% 64kb
-define(RumDefCheckInt, 1000).            %% 单位毫秒
-define(RumDefCheckHWM, undefined).
-define(RumDefFlushQueue, false).
-define(RumDefFlushThr, 10).
-define(RumDefFormatTer, rumFormatTer).
-define(RumDefFormatterCfg, []).

%% 默认日志文件选项
-define(RumDefHandler,
   [
      {rumBkdConsole, [{level, info}]},
      {rumBkdFile, [{id, error}, {file, <<"./log/error.log">>}, {level, '>=error'}, {size, 10485760}, {date, "$D0"}, {count, 5}]},
      {rumBkdFile, [{id, console}, {file, <<"./log/console.log">>}, {level, '>=debug'}, {size, 10485760}, {date, "$D0"}, {count, 5}]}
   ]).

-record(rumShaper, {
   id :: any()
   %% 每秒我们尝试传递多少消息
   , hwm = undefined :: 'undefined' | pos_integer()
   %% 这秒内我们收到了多少条消息
   , mps = 0 :: non_neg_integer()
   %% 当前秒
   , lastTime = rumTime:now() :: erlang:timestamp()
   %% 此秒内丢弃的消息数
   , dropped = 0 :: non_neg_integer()
   %% If true, flush notify messages from msg queue at overload
   %% 如果为true，则在过载时刷新来自消息队列的通知消息
   , flushQueue = true :: boolean()
   , flushThr = 0 :: integer()
   %% timer
   , timer = make_ref() :: reference()
   %% optional filter fun to avoid counting suppressed messages against HWM totals
   %% 可选的过滤器函数，以避免对HWM总数计算抑制消息
   , filter = fun(_) -> false end :: fun()
}).

-record(rumMsg, {
   severity :: rumAtomLevel()
   , pid :: pid()
   , node :: node()
   , module :: module()
   , function :: atom()
   , line :: integer()
   , metadata :: [tuple()]
   , datetime :: binary()
   , timestamp :: non_neg_integer()
   , message :: list()
   , destinations :: list()
}).

-type rumShaper() :: #rumShaper{}.
-type rumMsg() :: #rumMsg{}.

-type rumAtomLevel() :: none | debug | info | notice | warning | error | critical | alert | emergency.
-type rumMaskLevel() :: 0..256.

%% 日志等级列表
-define(RumLevels, [debug, info, notice, warning, error, critical, alert, emergency, none]).

-define(RunShouldLog(Sink, Level), (rumUtil:levelToNum(Level) band ?eRumCfg:get(Sink)) /= 0).

-define(RunShouldLog(Level), (rumUtil:levelToNum(Level) band ?eRumCfg:get(?RumDefSink)) /= 0).

-define(RunNotify(Level, Pid, Format, Args),
   gen_emm:info_notify(?RumDefSink, {mWriteLog, #rumMsg{severity = Level, pid = Pid, node = node(), module = ?MODULE, function = ?FUNCTION_NAME, line = ?LINE, metadata = [], datetime = rumUtil:msToBinStr(), timestamp = rumTime:nowMs(), message = eFmt:formatBin(Format, Args), destinations = []}})).

%%仅供内部使用仅内部非阻塞日志记录调用，当我们仍在启动大型啤酒时尝试进行日志记录（通常为错误）时，会有一些特殊处理。
-define(INT_LOG(Level, Format, Args),
   Self = self(),
   %%在生成中执行此操作，这样就不会导致从gen_event处理程序调用gen_event：which_handlers的死锁
   spawn(
      fun() ->
         case catch (gen_emm:which_epm(?RumDefSink)) of
            X when X == []; X == {'EXIT', noproc}; X == [rumBkdThrottle] ->
               %% there's no handlers yet or lager isn't running, try again
               %% in half a second.
               timer:sleep(500),
               ?RunNotify(Level, Self, Format, Args);
            _ ->
               case ?RunShouldLog(Level) of
                  true ->
                     ?RunNotify(Level, Self, Format, Args);
                  _ ->
                     ok
               end
         end
      end)).



